from fastapi import FastAPI, HTTPException, Request
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
from starlette.middleware.sessions import SessionMiddleware
from models.base_model import *
from models.user_model import *
from middlewares.middleware import BaseMiddleware
from settings import settings
from core import event
from api import api_router
import os

application = FastAPI(
    debug=settings.APP_DEBUG,
    docs_url=None,
    redoc_url=None,
)

# 配置静态文件目录
static_dir = settings.STATIC_ROOT
if not os.path.exists(static_dir):
    os.makedirs(static_dir)  # 如果目录不存在则创建
application.mount(settings.STATIC_URL, StaticFiles(directory=static_dir), name="static")

@application.get("/docs", include_in_schema=False)
async def swagger_ui():
    return get_swagger_ui_html(
        openapi_url="/openapi.json",
        title="Swagger UI",
    )

@application.get("/redoc", include_in_schema=False)
async def redoc():
    return get_redoc_html(
        openapi_url="/openapi.json",
        title="ReDoc",
    )

# 事件监听
application.add_event_handler("startup", event.startup(application))
application.add_event_handler("shutdown", event.stopping(application))

application.add_middleware(BaseMiddleware)

application.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
    allow_methods=settings.CORS_ALLOW_METHODS,
    allow_headers=settings.CORS_ALLOW_HEADERS,
)

application.add_middleware(
    SessionMiddleware,
    secret_key=settings.SECRET_KEY,
    session_cookie=settings.SESSION_COOKIE,
    max_age=settings.SESSION_MAX_AGE
)

@application.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    # 打印请求数据
    print("原始请求数据:", exc.body)
    # 打印校验错误信息
    print("校验错误信息:", exc.errors())
    
    # 可以选择将错误信息返回给客户端
    return JSONResponse(
        status_code=422,
        content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),
    )

# 路由
application.include_router(api_router)

app = application